package top.lshaci.learning.thread;

import java.util.concurrent.*;

/**
 * CompletableFutureTest
 *
 * @author lshaci
 * @since 1.0.0
 */
public class CompletableFutureTest {

    static ExecutorService executorService = Executors.newFixedThreadPool(4);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
//        CompletableFuture.runAsync(() -> {
//            System.err.println("执行异步任务");
//        }, executorService);

//        CompletableFuture<String> supplyAsync = CompletableFuture.supplyAsync(() -> {
//            System.err.println("有返回值的异步任务");
//            int i = 1 / 0;
//            return "我有返回值";
//        }, executorService).whenComplete((res, e) -> {
//            System.err.println("上一个任务的结果是：" + res);
//            System.err.println("上一个任务的异常是：" + e);
//        }).exceptionally(e -> {
//            System.err.println("发生异常了....");
//            return "null";
//        });
//        String result = supplyAsync.get();
//        System.err.println("Main线程中获取到返回值：" + result);

//        CompletableFuture<String> supplyAsync1 = CompletableFuture.supplyAsync(() -> {
//            System.err.println("有返回值的异步任务");
//            int i = 1 / 0;
//            return "我有返回值";
//        }, executorService).handle((res, ex) -> {
//            System.err.println("上一个任务的结果是：" + res);
//            System.err.println("上一个任务的异常是：" + ex);
//            return "完成了";
//        });
//        String result1 = supplyAsync1.get();
//        System.err.println("Main线程中获取到返回值：" + result1);

        /**
         * thenRunAsync 不能获取到上一步的结果
         */
//        CompletableFuture<Void> futureThenRun = CompletableFuture.supplyAsync(() -> {
//            System.err.println("有返回值的异步任务");
//            int i = 1 / 0;
//            return i;
//        }, executorService).thenRunAsync(() -> {
//            System.err.println("执行第二个任务");
//        }, executorService);

        /**
         * thenAcceptAsync 能获取到上一步的结果, 没有返回值
         */
//        CompletableFuture<Void> futureThenAccept = CompletableFuture.supplyAsync(() -> {
//            System.err.println("有返回值的异步任务");
//            int i = 10 / 2;
//            return i;
//        }, executorService).thenAcceptAsync(res -> {
//            System.err.println("获取到了上一个任务的结果：" + res);
//            System.err.println("执行第二个任务");
//        }, executorService);

        /**
         * thenApplyAsync 能获取到上一步的结果, 有返回值（能改变返回值）
         */
//        CompletableFuture<Integer> futureThenApply = CompletableFuture.supplyAsync(() -> {
//            System.err.println("有返回值的异步任务");
//            int i = 10 / 2;
//            return i;
//        }, executorService).thenApplyAsync(res -> {
//            System.err.println("获取到了上一个任务的结果：" + res);
//            System.err.println("执行第二个任务");
//            int j = res + 13;
//            return j;
//        }, executorService);
//        Integer integer = futureThenApply.get();
//        System.err.println("Main中获取到了futureThenApply的返回值：" + integer);

        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            System.err.println("任务1执行。。。");
            int i = 10 / 2;
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                System.err.println("任务1执行完成。。。");
            }
            return i;
        }, executorService);
//        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
//            System.err.println("任务2执行。。。");
//            try {
//                return "hello ";
//            } finally {
//                System.err.println("任务2执行完成。。。");
//            }
//        }, executorService);
/**
 * 两个任务都要完成才执行 任务3
 * 1.runAfterBothAsync 拿不到两个任务的返回值，没有返回值
 * 2.thenAcceptBothAsync 能不到两个任务的返回值，没有返回值
 * 3.thenCombineAsync 能不到两个任务的返回值，有返回值
 */
//        future1.runAfterBothAsync(future2, () -> {
//            System.err.println("任务3执行。。。");
//        }, executorService);

//        future1.thenAcceptBothAsync(future2, (res1, res2) -> {
//            System.err.println("任务3执行。。。");
//            System.err.println("任务1结果。。。" + res1);
//            System.err.println("任务2结果。。。" + res2);
//        }, executorService);

//        CompletableFuture<String> future3 = future1.thenCombineAsync(future2, (res1, res2) -> {
//            System.err.println("任务3执行。。。");
//            System.err.println("任务1结果。。。" + res1);
//            System.err.println("任务2结果。。。" + res2);
//            return res1 + ":" + res2;
//        }, executorService);
//        System.err.println("Main线程中任务3的结果：" + future3.get());
/**
 * 两个任务只要完成一个就可以执行 任务3
 * 1.runAfterEitherAsync 拿不到两个任务的返回值，没有返回值
 * 2.acceptEitherAsync 拿到最先完成那个任务的返回值，没有返回值
 * 3.applyToEitherAsync 拿到最先完成那个任务的返回值，有返回值
 */
//        future1.runAfterEitherAsync(future2, () -> {
//            System.err.println("任务3执行。。。");
//        }, executorService);

        CompletableFuture<Integer> future22 = CompletableFuture.supplyAsync(() -> {
            System.err.println("任务2执行。。。");
            try {
                TimeUnit.SECONDS.sleep(6);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                System.err.println("任务2执行完成。。。");
            }
            return 22;
        }, executorService);
//        future1.acceptEitherAsync(future22, (res) -> {
//            System.err.println("任务3 => 获取到的返回值：" + res);
//        }, executorService);

        CompletableFuture<Integer> future3 = future1.applyToEitherAsync(future22, res -> {
            System.err.println("任务3 => 获取到的返回值：" + res);
            return res + 33;
        }, executorService);
        System.err.println("Main方法中拿到future3的返回值：" + future3.get());
    }
}
